package com.jvm;

import java.util.HashSet;
import java.util.Set;

/**
 * 运行时常量池导致的内存溢出
 *  -XX:PermSize=6M -XX:MaxPermSize=6M
 *  测试时首先以JDK 6来运行代码,
 *  而使用JDK 7或更高版本的JDK来运行这段程序并不会得到相同的结果，无论是在JDK 7中继续使
 * 用-XX：MaxPermSize参数或者在JDK 8及以上版本使用-XX：MaxMeta-spaceSize参数把方法区容量同
 * 样限制在6MB，也都不会重现JDK 6中的溢出异常，循环将一直进行下去，永不停歇[1]。出现这种变
 * 化，是因为自JDK 7起，原本存放在永久代的字符串常量池被移至Java堆之中，所以在JDK 7及以上版
 * 本，限制方法区的容量对该测试用例来说是毫无意义的。这时候使用-Xmx参数限制最大堆到6MB就能
 * 够看到以下两种运行结果之一，具体取决于哪里的对象分配时产生了溢出
 */
public class RuntimeConstantOOM {

    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        short i = 0;
        while (true){
            //String::intern()是一个本地方法，它的作用是如果字符串常量池中已经包含一个等于此String对象的
            //字符串，则返回代表池中这个字符串的String对象的引用；
            set.add(String.valueOf(i++).intern());
        }
    }
}
